package cn.janescott.file.server;

import cn.janescott.file.server.dao.FileDao;
import cn.janescott.file.server.exception.MyExceptionEnums;
import cn.janescott.file.server.processor.BinaryProcessor;
import cn.janescott.file.server.servlet.FileServlet;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 启动类
 *
 * @author scott
 * @date 2019/4/12
 */
public class FileServerStarter {
    /**
     * 日志
     */
    private static Logger logger = LoggerFactory.getLogger(FileServerStarter.class);

    /**
     * 对象池
     */
    public static Map<Class, Object> beanMap = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        Server server = new Server(8080);
        ServletContextHandler context = new ServletContextHandler(server, "/");
        /*
         * 文件服务器
         */
        context.addServlet(FileServlet.class, "/upload");
        try {
            server.start();
            System.out.println("server starting!");
            init();
            System.out.println("server started!");
        } catch (Exception ex) {
            /*
             * 启动失败
             */
            logger.error(ex.getMessage(), ex);
            /*
             * 退出程序
             */
            System.exit(-1);
        }

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                server.stop();
            } catch (final Exception e) {
                /*
                 * 关闭失败
                 */
                logger.error(e.getMessage(), e);
                /*
                 * 退出
                 */
                System.exit(-1);
            }
        }));
        try {
            server.join();
        } catch (Exception ex) {
            /*
             * 挂起失败
             */
            logger.error(ex.getMessage(), ex);
            /*
             * 退出
             */
            System.exit(-1);
        }
    }

    /**
     * 初始化
     */
    private static void init() {
        //0、类加载器
        logger.info("get class loader");
        ClassLoader classLoader = FileServerStarter.class.getClassLoader();

        //1、初始化数据库连接
        logger.info("init datasource");
        try {
            InputStream dbIn = classLoader.getResourceAsStream("dbcp.properties");
            Properties dbProps = new Properties();
            dbProps.load(dbIn);
            DataSource dataSource = BasicDataSourceFactory.createDataSource(dbProps);
            beanMap.put(DataSource.class, dataSource);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            System.exit(-1);
        }

        //2、初始化dao
        logger.info("init fileDao");
        FileDao fileDao = new FileDao();
        beanMap.put(FileDao.class, fileDao);

        //3、初始化processor
        logger.info("init binary processor");
        try {
            InputStream in = classLoader.getResourceAsStream("app.properties");
            Properties props = new Properties();
            props.load(in);
            String dir = props.getProperty("dir", "/dir");
            int bufferSize = Integer.parseInt(props.getProperty("bufferSize", "1024"));
            File dirFile = new File(dir);
            if (dirFile.exists() || dirFile.mkdirs()) {
                BinaryProcessor processor = new BinaryProcessor();
                processor.setDir(dir);
                processor.setBufferSize(bufferSize);
                beanMap.put(BinaryProcessor.class, processor);
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            System.exit(-1);
        }
    }

    /**
     * 获取实例
     *
     * @param clazz
     * @return
     */
    public static Object get(Class clazz) {
        /*
         * 初始化缺失对象
         */
        if (!beanMap.containsKey(clazz)) {
            logger.error(String.format("[code=%s;message=%s;class=%s]", MyExceptionEnums.BEAN_LEAK_EXCEPTION.getCode(), MyExceptionEnums.BEAN_LEAK_EXCEPTION.getMessage(), clazz));
            System.exit(-1);
        }

        /*
         * 对象失效
         */
        Object o = beanMap.get(clazz);
        if (o == null) {
            logger.error(String.format("[code=%s;message=%s;class=%s]", MyExceptionEnums.BEAN_EXPIRE_EXCEPTION.getCode(), MyExceptionEnums.BEAN_EXPIRE_EXCEPTION.getMessage(), clazz));
            System.exit(-1);
        }
        return o;
    }
}
